﻿//-----------------------------------------------------------------------
// <copyright file="UpdateBinariesStage.cs" author="Artak Mkrtchyan">
//     Creative Commons - GNU General Public License (http://creativecommons.org/licenses/GPL/2.0/
// </copyright>
// <author>Artak Mkrtchyan</author>
// <email>mkArtak@gmail.com</email>
// <date>20/03/2013</date>

using ConsoleHoster.Common.Utilities;
using ConsoleHoster.Common.Utilities.IO;
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;

namespace AppUpdateInstaller.Model.InstallationStages
{
	internal sealed class UpdateBinariesStage : InstallationStageBase
	{
		private readonly string updateFolder;
		private readonly string binariesFolder;

		public UpdateBinariesStage(string argBinariesFolder, string argUpdateFolder, IFileSystemContentProvider argFileSystemContentProvider, IProcessManager argProcessManager, Action argShutdownLogic)
			: base(argProcessManager, argFileSystemContentProvider, argShutdownLogic)
		{
			if (!this.FileSystemContentProvider.DirectoryExists(argBinariesFolder))
			{
				throw new ArgumentException("The installation folder doesn't exist");
			}

			if (!this.FileSystemContentProvider.DirectoryExists(argUpdateFolder))
			{
				throw new ArgumentException("The update folder doesn't exist");
			}

			this.updateFolder = argUpdateFolder;
			this.binariesFolder = argBinariesFolder;
		}

		public override void Run()
		{
			this.NotifyProgressChange(new InstallationStageProgressEventArgs { Status = "Updating application binaries..." });
			this.CopyDirectoryContent(this.updateFolder, this.binariesFolder);
		}

		public override void FinalizeStage()
		{
			this.NotifyProgressChange(new InstallationStageProgressEventArgs { Status = "Starting updated app" });
			string tmpNewUpdaterPath = Path.Combine(this.binariesFolder, Assembly.GetExecutingAssembly().GetName().Name + ".exe");
			using (Process tmpProcess = this.ProcessManager.StartProcess(tmpNewUpdaterPath, StringUtilities.Format("{0} {1} {2}", InstallerMode.CleanupUpdateBinaries.ToString(), this.updateFolder, this.binariesFolder)))
			{
				tmpProcess.WaitForInputIdle();
			}

			if (this.ShutdownAction != null)
			{
				this.ShutdownAction();
			}
		}

		private void CopyDirectoryContent(string argSourceFolder, string argDestinationFolder)
		{
			if (!this.FileSystemContentProvider.DirectoryExists(argDestinationFolder))
			{
				this.FileSystemContentProvider.CreateDirectory(argDestinationFolder);
			}

			foreach (string tmpFile in this.FileSystemContentProvider.GetFiles(argSourceFolder))
			{
				this.FileSystemContentProvider.CopyFile(tmpFile, Path.Combine(argDestinationFolder, Path.GetFileName(tmpFile)), true);
			}

			foreach (string tmpDirectory in Directory.GetDirectories(argSourceFolder))
			{
				CopyDirectoryContent(tmpDirectory, Path.Combine(argDestinationFolder, tmpDirectory));
			}
		}

		public override bool HasFinalizerStage
		{
			get
			{
				return true;
			}
		}

		public override bool SupportsRollback
		{
			get
			{
				return false;
			}
		}
	}
}
